package com.wjc.httpserver;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.channels.SocketChannel;
import java.util.Date;

import com.wjc.http.Dispatcher;
import com.wjc.http.HttpRequest;
import com.wjc.http.HttpRequestFactory;
import com.wjc.http.HttpResponse;
import com.wjc.http.util.NIOServer;
import com.wjc.http.util.PipServer;
import socks.CProxy;
import socks.SocksException;
import socks.SocksSocket;
import android.util.Log;

/**
 * 用来维护一个client 和proxy 的连接
 * 
 * @author wjc
 * */
public class Socket5Connection {
	private static final String TAG = "Socket5Connection";
	/**
	 * 客户端连接
	 * */
	private Socket clientSocket;
	/**
	 * 目标主机连接
	 * */
	private Socket targetSocket;
	private CProxy proxySet;

	private static int state;// 用来结束运行
	public static final int RUN = 0x1;
	public static final int STOP = 0x2;
	public static NIOServer se = new NIOServer();
	public static PipServer pip = new PipServer();
	/**
	 * 连接超时时长
	 * */
	private static int socketOutTime = 30 * 1000;

	public boolean doDispose() {

		try {

			HttpRequest firstrequest = HttpRequestFactory.read(
					clientSocket.getInputStream(),
					clientSocket.getOutputStream());
			Log.d(TAG,
					"创建到代理" + proxySet.getInetAddress() + ":"
							+ proxySet.getPort() + "的连接");

			if (firstrequest.getMethod().equals("CONNECT")) {
				Log.d(TAG + Thread.currentThread().getId(), "连接到"
						+ firstrequest.toString());
				Log.d(TAG, "https 访问");
				String s = firstrequest.getRequestURL();
				int index = s.indexOf(':');
				String host = s.substring(0, index);
				String p = s.substring(index + 1);
				int port = Integer.valueOf(p);
				if (port != 443) {
					Log.d(TAG, "非安全端口访问");
					clientSocket.close();
					return false;
				} else {
					Log.d(TAG, "正在建立连接");
					clientSocket.setKeepAlive(true);
					targetSocket = new SocksSocket(proxySet, host, port);

					targetSocket.setKeepAlive(true);
					clientSocket.setSoTimeout(socketOutTime);
					targetSocket.setSoTimeout(socketOutTime);
					OutputStream out = clientSocket.getOutputStream();
					out.write("HTTP/1.1 200 Connection Established\r\n\r\n"
							.getBytes());
					out.flush();
					// targetSocket.setSoTimeout(socketOutTime);
					Log.d(TAG, "加入隧道");
					pip.addSocket(clientSocket, targetSocket);
					Log.d(TAG, "结束");
					return true;
				}
			} else {
				Log.d(TAG + Thread.currentThread().getId(),
						"连接到" + firstrequest.getRemoteHost() + ":"
								+ firstrequest.getRemotePort());// +firstrequest.toString());
				targetSocket = new SocksSocket(proxySet,
						firstrequest.getRemoteHost(),
						firstrequest.getRemotePort());

				clientSocket.setSoTimeout(socketOutTime);
				targetSocket.setSoTimeout(socketOutTime);
				clientSocket.setKeepAlive(true);
				targetSocket.setKeepAlive(true);
				Dispatcher.dispatch(firstrequest, targetSocket);

				se.addSocket(clientSocket, targetSocket,
						firstrequest.getRemoteHost());

				return true;
			}
		} catch (SocketTimeoutException e) {
			e.printStackTrace();

			if (clientSocket != null)
				try {
					OutputStream out = clientSocket.getOutputStream();
					setErrorInfo(out, e);
					clientSocket.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			if (targetSocket != null)
				try {
					targetSocket.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			Log.d(TAG, "连接出错 :" + e.getMessage());
			return false;

		} catch (SocksException e) {
			e.printStackTrace();

			if (clientSocket != null)
				try {
					OutputStream out = clientSocket.getOutputStream();
					setErrorInfo(out, e);
					clientSocket.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			if (targetSocket != null)
				try {
					targetSocket.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			Log.d(TAG, "连接出错 :" + e.getMessage());
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block

			e.printStackTrace();
			return false;
		} catch (NullPointerException e) {
			e.printStackTrace();
			return false;
		}

		finally {
			state = STOP;
		}
	}

	/**
	 * 客户端连接传入后，将分析
	 * 
	 * @param client
	 *            客户端 连接
	 * 
	 * @throws IOException
	 * */
	public Socket5Connection(Socket client, CProxy proxySet) throws IOException {
		this.clientSocket = client;
		this.proxySet = proxySet;
		state = RUN;
		doDispose();

	}

	public int getState() {
		return state;
	}

	public static synchronized void setState(int state) {
		Socket5Connection.state = state;
	}

	private void setErrorInfo(OutputStream out, Exception e) {

		StringBuffer response = new StringBuffer();
		StringBuffer errorpage = new StringBuffer();
		errorpage.append("<html><head><title>http proxy</title></head><body>");
		errorpage.append("<h1 align=\"center\">http proxy server Error</h1>");
		errorpage.append("<h2 align=\"center\">Error Info:" + e.toString()
				+ "</h1>");
		errorpage.append("</body></html");
		response.append("HTTP/1.1 200 OK\r\n");
		response.append("Content-Type: text/html;charset=utf-8\r\n");
		byte info[] = errorpage.toString().getBytes();
		response.append("Content-Length: " + info.length + "\r\n");
		response.append("Connection: Close\r\n\r\n");
		try {
			out.write(response.toString().getBytes());
			Log.d(TAG, "发送错误信息" + response + errorpage);
			out.write(info);
			out.flush();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}
}
